/* 这是一个并行文件的复制程序，main程序有三个命令行参数： 
 * 一个输入文件的基本名、一个输出文件的基本名和要复制的文件数
 * 程序创建了numcopies线程，线程i将infile.i复制到outfile.i中
 */
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "restart.h"

#define MAXNAME 80
#define R_FLAGS O_RDONLY
#define W_FLAGS (O_WRONLY | O_CREAT)
#define W_PERMS (S_IRUSR | S_IWUSR)

typedef struct {
    int args[3];
    pthread_t tid;
} copy_t;

// 拷贝函数
void *copyfilepass(void *arg);

int main(int argc, char *argv[]) {
    int *bytesp, error;
    copy_t *copies;
    char filename[MAXNAME];
    int i, numcopiers, totalbytes = 0;

    if (argc != 4) {
        fprintf(stderr, "Usage: %s infile outfile copies\n", argv[0]);
        return 1;
    }

    numcopiers = atoi(argv[3]);
    if ((copies = (copy_t *)calloc(numcopiers, sizeof(copy_t))) == NULL) {
        perror("Failed to allocate copier space");
        return 1;
    }

    // 打开源和目标文件，并创建线程
    for (i = 0; i < numcopiers; i++) {
        copies[i].tid = pthread_self(); // 不能是新线程的值

        // 将文件名的值写入到filename中
        if (snprintf(filename, MAXNAME, "%s.%d", argv[1], i+1) == MAXNAME) {
            fprintf(stderr, "Input filename %s.%d too long", argv[1], i + 1);
            continue;
        }

        // 打开文件args[0]
        if ((copies[i].args[0] = open(filename, R_FLAGS)) == -1) {
            fprintf(stderr, "Failed to open source file %s: %s \n", filename, strerror(errno));
            continue;
        }

        // 打开文件args[1]
        if ((copies[i].args[1] = open(filename, W_FLAGS, W_PERMS)) == -1) {
            fprintf(stderr, "Failed to open destination file %s: %s\n", filename, strerror(errno));
            continue;
        }

        if (error = pthread_create((&copies[i].tid), NULL, copyfilepass, copies[i].args)) {
            fprintf(stderr, "Failed to create thread %d : %s\n", i + 1, strerror(error));
            copies[i].tid = pthread_self();     // 不能是新线程的值
        }
    }

    // 等待线程结束，并报告总字节数
    for (i = 0; i < numcopiers; i++) {
        // 未创建
        if (pthread_equal(copies[i].tid, pthread_self())) {
            continue;
        }

        if (error = pthread_join(copies[i].tid, (void**)&bytesp)) {
            fprintf(stderr, "Failed to join thread %d\n", i);
            continue;
        }

        printf("Thread %d copied %d bytes from %s.%d to %s.%d\n", i, *bytesp, argv[1], i + 1, argv[2], i + 1);
        
        totalbytes += *bytesp;
    }

    printf("Total bytes copied = %d\n", totalbytes);
    return 0;
}


void *copyfilepass(void *arg) {
    int *argint;

    argint = (int *)arg;
    argint[2] = copyfile(argint[0], argint[1]);
    close(argint[0]);
    close(argint[1]);

    return argint + 2;
}